package com.study.jdk.j8;

import org.junit.Test;

import java.io.PrintStream;
import java.util.Arrays;
import java.util.Comparator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * @program: juc-study
 * @author: jzhou
 * @date: 2022-08-29 10:45
 * @version: 1.0
 * @description: 方法引用
 * 1.使用情况：当要传递给 Lambda 体的操作已经有实现的方法了，可以使用方法引用！
 * 2.方法引用本质上就是 lambda 表达式，而 lambda 表达式作为函数式接口的实例。所以
 *   方法引用也是函数式接口的实例
 * 3.使用格式：类(对象) :: 方法名
 * 4.具体分为三种情况
 *      对象 :: 非静态方法
 *      类 :: 静态方法
 *      类 :: 非静态方法
 * 你的抽象方法已经有人实现啦，参数列表和返回值类型和接口定义的都是一直的
 * 5.方式引用使用要求： 接口中抽象方法的形参列表和返回值与方法引用的要一直
 **/
public class LambdaMethodRefStudy {
	@Test
	public void test01(){
		// 情况一：对象 :: 实例方法
		PrintStream ps = System.out;
		// 不需要写参数， 可以理解为参数已经在函数式接口的方法中定义了，
		// 传入参数类型已在函数式接口的泛型上做了约束，参数个数也在类上做了约束
		// 该处执行方法的声明，实际参数在使用时必须传递
		Consumer<String> consumer = ps :: println;
		consumer.accept("beijing");

		// 情况二：类 :: 静态方法
		Comparator<Integer> comparator = Integer::compare;
		System.out.println(comparator.compare(2,5));

        // 情况三：类 :: 非静态方法
		Comparator<String> comparator1 = String::compareTo;
		System.out.println(comparator1.compare("abc", "abd"));
	}

	// 构造器引用
	@Test
	public void test02(){
		Supplier<LambdaMethodRefStudy> supplier = LambdaMethodRefStudy::new;
		System.out.println(supplier.get());
	}

	// 数组引用
	@Test
	public void test03(){
		Function<Integer,String[]> function = len -> new String[len];
		String[] apply = function.apply(5);
		System.out.println(Arrays.toString(apply));

		Function<Integer,String[]> fun2 = String[]::new;
		String[] app2 = fun2.apply(3);
		System.out.println(Arrays.toString(app2));

	}
}
